#pragma once

#include "Thread.hpp"
#include "BlockQueue.hpp"
#include <vector>
#include <iostream>

namespace yui
{
    template <class T>
    class ThreadPool
    {
    private:
        // 复制拷贝禁用
        ThreadPool(int num = NUM)
            : _threadNum(num)
        {
        }
        ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;
        ThreadPool(const ThreadPool<T> &) = delete;

    public:
        static ThreadPool *getInstance()
        {
            // 加锁
            if (_threadPool == nullptr)
            {
                pthread_mutex_lock(&_mutex);
                if (_threadPool == nullptr)
                {
                    _threadPool = new ThreadPool(5);
                }
                // 解锁
                pthread_mutex_unlock(&_mutex);
            }

            return _threadPool;
        }
        ~ThreadPool()
        {
            for (auto &x : _threads)
            {
                x.Stop();
            }
        }
        void init()
        {
            for (int i = 0; i < _threadNum; ++i)
            {
                std::string name = "thread-" + std::to_string(i + 1);
                _threads.emplace_back(std::bind(&ThreadPool::HanderTask, this, std::placeholders::_1), name);
            }
        }
        void start()
        {
            for (auto &x : _threads)
            {
                x.Start();
            }
        }
        void HanderTask(std::string name)
        {
            // pthread_detach(pthread_self());
            while (true)
            {

                T task;
                _threadTasks.pop(&task);
                cout << "取到任务：" << task << endl;
            }
        }
        void pushTask(const T &task)
        {
            _threadTasks.push(task);
        }

    private:
        std::vector<yui::Thread> _threads;
        yui::BlockQueue<T> _threadTasks;
        int _threadNum;
        static ThreadPool *_threadPool;
        static pthread_mutex_t _mutex;
    };
    template <class T>
    ThreadPool<T> *ThreadPool<T>::_threadPool = nullptr;
    template <class T>
    pthread_mutex_t ThreadPool<T>::_mutex = PTHREAD_MUTEX_INITIALIZER;
}